//
//  Plane.cpp
//  RayTracer
//
//  Created by 俞云康 on 3/25/16.
//  Copyright © 2016 yushroom. All rights reserved.
//

#include "Plane.hpp"
#include "Params.hpp"

Plane::Plane(const std::string& name,
      const std::shared_ptr<Transform>& transform)
    :   Shape(name, transform)
{
    normal = transform->normal2world(Normal(0, 0, 1));
    normal.normalize_self();
    Position p = transform->point2world(Position(0, 0, 0));
    D = -Dot(normal, p);
    //info("%s\n", name.c_str());
    //info("  normal = (%lf %lf %lf)\n", normal.x, normal.y, normal.z);
    //info("  p      = (%lf %lf %lf)\n", p.x, p.y, p.z);
    //info("  D      = %lf\n", D);
}

shared_ptr<Shape> Plane::create(const Params& params) {
    string name = params.getID();
    auto transform = Transform::create(params.child("transform"));
    return make_shared<Plane>(name, transform);
}

bool Plane::intersect(const Ray& r, HitInfo* hit) const {
    float n_dot_d = Dot(normal, r.dir);
    // ray from back
    if (n_dot_d > 0) {
        return false;
    }
    if (n_dot_d != 0) {
        float t = -(D + Dot(normal, r.o)) / n_dot_d;
        if (t > EPS && t < r.maxt) {
            r.maxt = t;
            hit->position = r.o + r.dir * t;
            hit->normal = normal;
            //hit->texcoord = {Dot(hit->position, tangent), Dot(hit->position, bitangent)};
            Position p = transform->point2world(hit->position);
            //Assert(is_zero(p.y));
            hit->texcoord.x = p.x;
            hit->texcoord.y = p.y;
            //cout << "hit plane.\n";
            //cout << "hit " << name  << " depth: " << r.depth << endl;
            return true;
        }
    }
    return false;
}

bool Plane::intersect(const Ray& r) const {
    float n_dot_d = Dot(normal, r.dir);
    if (n_dot_d != 0) {
        float t = -(D + Dot(normal, r.o)) / n_dot_d;
        return (t > EPS && t < r.maxt);
    }
    return false;
}